<?php
namespace app\push\controller;

use think\Session;
use think\Cache;
use think\Db;
use think\Controller;
use app\common\model\Users as UsersModel;
use app\common\model\Csuser as CsuserModel;
use app\common\util\WechatThirdUtil;
use app\common\model\WxUser as WxUserModel;
use app\common\model\AuthorWxUser as AuthorWxUserModel;

class Run extends Controller{
    protected $users_model;
    protected $csuser_model;
    protected $author_wx_user_model;
    protected $wx_user_model;

    public function _initialize(){
        parent::_initialize();
        $this->users_model = new UsersModel;
        $this->csuser_model = new CsuserModel;
        $this->author_wx_user = new AuthorWxUserModel;
        $this->wx_user_model = new WxUserModel;

        //创建websocket服务器对象，监听0.0.0.0:9502端口
        $ws = new \swoole_websocket_server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);

        $setConfig = [
            'daemonize' => 1,
            // 'heartbeat_check_interval' => 5,//心跳机制
            'ssl_cert_file' => '/usr/local/nginx/conf/ssl/'.SOCKET_URL.'.crt',
            'ssl_key_file' => '/usr/local/nginx/conf/ssl/'.SOCKET_URL.'.key'
        ];

        $ws->set($setConfig);

        $this->event($ws);

        $ws->start();
    }

    public function event($ws){
         //监听WebSocket连接打开事件
         $ws->on('open', function ($ws, $request) {
            // var_dump($request->fd, $request->get, $request->server);
            // $ws->push($request->fd, json_encode(['msg' => 'hello, welcome']));
        });

        //监听WebSocket消息事件
        $ws->on('message', function ($ws, $frame) {
            // echo "Message: {$frame->data}\n";
            $data = json_decode($frame->data,true);
            $message_type = $data['type'];
            switch($message_type){
                case 'init':
                    //登录 绑定uid
                    $uid = $data['data']['id']; 
                    $this->bindUid($frame->fd, $uid);
                    $message = [
                        'message_type' => 'init',
                        'data' => [
                            'id' => $uid,
                        ],
                    ];
                    Session::set('admin_id',$uid);
                    $this->sendToUid($ws,$uid,$message);
                    break;
                case 'current_csuser_count':
                    $auid = $data['data']['id'];
                    $count = $this->csuser_model->field("count(*) as valid_count,(SELECT count(*) FROM think_csuser where auid = {$auid} AND status = 1 AND type = 1) as online_count")->where('auid',$auid)->where('status',1)->find();
                    $message = [
                        'message_type' => 'current_csuser_count',
                        'data' => [
                            'id' => $data['data']['id'],
                            'current_csuser_count' => $count,
                        ],
                    ];

                    $uid = $data['data']['uid'];
                    $this->sendToUid($ws,$uid,$message);
                    if($uid !== 1){
                        $this->sendToAdmin($ws,$message);
                    }
                    break;
                case 'current_subscribe_count':
                    $id = $data['data']['id'];
                    //当日关注数
                    $count = $this->users_model->where('auid',$id)->whereTime('subscribe_time', 'd')->count();

                    $message = [
                        'message_type' => 'current_subscribe_count',
                        'data' => [
                            'id' => $data['data']['id'],
                            'current_subscribe_count' => $count,
                        ]
                    ];

                    $uid = $data['data']['uid'];
                    $this->sendToUid($ws,$uid,$message);
                    if($uid !== 1){
                        $this->sendToAdmin($ws,$message);
                    }
                    break;
                case 'current_butt_count':
                    $id = $data['data']['id'];
                    //当日对接数
                    $count = $this->users_model->where('auid',$id)->whereTime('create_butt_time', 'd')->count();

                    $message = [
                        'message_type' => 'current_butt_count',
                        'data' => [
                            'id' => $data['data']['id'],
                            'current_butt_count' => $count,
                        ]
                    ];

                    $uid = $data['data']['uid'];
                    $this->sendToUid($ws,$uid,$message);
                    if($uid !== 1){
                        $this->sendToAdmin($ws,$message);
                    }
                    break;
                case 'current_msg_count':
                    $id = $data['data']['id'];
                    //当日消息数
                    $cs_ids = $this->csuser_model->where('auid',$id)->where('status',1)->group('auid')->value('group_concat(id) as cs_ids');
                    $count = Db::connect('db_config_chatlog')
                                                    ->name('chatlog')
                                                    ->where('send_type',1002)
                                                    ->whereIn('cs_id',$cs_ids)
                                                    ->whereTime('send_time', 'd')
                                                    ->count();

                    $message = [
                        'message_type' => 'current_msg_count',
                        'data' => [
                            'id' => $data['data']['id'],
                            'current_msg_count' => $count,
                        ]
                    ];
                    $uid = $data['data']['uid'];
                    $this->sendToUid($ws,$uid,$message);
                    if($uid !== 1){
                        $this->sendToAdmin($ws,$message);
                    }
                    break;
                case 'push_message':
                    $message = [
                        'message_type' => 'push_message',
                        'data' => [
                            'title' => $data['data']['title'],
                            'message' => $data['data']['message'],
                        ]
                    ];
                    $uid = $data['data']['uid'];
                    $this->sendToUid($ws,$uid,$message);
                    if($uid !== 1){
                        $this->sendToAdmin($ws,$message);
                    }
                    break;
                case 'time_after':
                    //定时任务
                    // $data = [
                    //     'setTime' => $setTime,
                    //     'date' => $date,
                    //     'everyday' => true,
                    // ];
                    $date = date('H:i:s');
                    $setTime = ($data['data']['timer'] - time())*1000;
                    swoole_timer_after($setTime, function()use($setTime,$date){
                        //给用户发消息
                        $third_config = $this->wx_user_model->find(); //第三方开发平台信息
                        $config = $this->author_wx_user->field('authorizer_access_token,authorizer_expires,appid,id,authorizer_refresh_token')->where('id',1)->find();
                        $wechatObj = new WechatThirdUtil($third_config , $config);
                        $content = '发送定时消息[创建时间:'.$date.'|发送时间:'.date('H:i:s').']:晚上好,测试每天定时任务第一次发送';
                        $openid = 'oo5pZ0xTFIU313KP-FHqmdRlzT3w';
                        $res = $wechatObj->sendMsgToOne($openid, $content);
                        // $res = $wechatObj->sendMsgToAll($content);
                        $everyday = true;
                        if($everyday == true){ //每天循环发
                            $today_time = date('Y-m-d H:i:s');
                            // $timer_id = swoole_timer_tick(86400*1000, function()use($today_time){
                            $wait_time = 86400*1000 - 1;
                            $timer_id = swoole_timer_tick($wait_time, function()use($wechatObj,$today_time,$openid){
                                $content = '发送定时消息[创建时间:'.$today_time.'|发送时间:'.date('Y-m-d H:i:s').']:测试每隔一天循环发送定时任务';
                                // $res = $wechatObj->sendMsgToAll($content);
                                $res = $wechatObj->sendMsgToOne($openid, $content);
                            });
                        }
                    });
                    break;
                case 'clear_timer':
                    $Timer_id = $data['Timer_id'];
                    $result = swoole_timer_clear($Timer_id);
                    if ($result) {
                        echo '已清除';
                    } else {
                        echo '未清除';
                    }
                default:
                    break;
            }
        });

        //监听WebSocket连接关闭事件
        $ws->on('close', function ($ws, $fd) {
            $uid = session::get('admin_id');
            $this->unBindUid($fd,$uid);
            echo "client-{$fd} is closed\n";
        });
    }

    /**
     * 发送指定用户
     */
    private function sendToUid($ws,$uid,$message){
        if(Cache::has("user{$uid}")){
            //有用户在线
            $connections = Cache::get("user{$uid}");
            foreach($connections as $k=>$fd){
                if($ws->exist($fd)){
                    $ws->push($fd, json_encode($message));
                }else{
                    unset($connections[$k]);
                    if($connections == []){
                        Cache::rm("user{$uid}");
                        return;
                    }
                    Cache::set("user{$uid}",array_unique($connections));
                }
            }
        }else{
            //没有用户在线
        }
    }

    /**
     * 发送全部用户
     */
    private function sendAll($ws){
        foreach($ws->connections as $fd){
            if($ws->exist($fd)){
                $ws->push($fd, json_encode($message));
            }
        }
    }

    /**
     * 绑定fd uid 创建fd 用户uid的映射关系
     */
    private function bindUid($fd,$uid){
        $fd_arr = [];
        if(Cache::has("user{$uid}")){
            $fd_arr = Cache::get("user{$uid}");
            $fd_arr[] = $fd;
            Cache::set("user{$uid}",array_unique($fd_arr));
        }else{
            $fd_arr = [
                $fd,
            ];
            Cache::set("user{$uid}",array_unique($fd_arr));
        }
    }

    private function unBindUid($fd,$uid){
        if(Cache::has("user{$uid}")){
            $fd_arr = Cache::get("user{$uid}");
            foreach($fd_arr as $k => $v){
                if($v == $fd) unset($fd_arr[$k]);
                if($fd_arr == []){
                    Cache::rm("user{$uid}");
                }else{
                    Cache::set("user{$uid}",array_unique($fd_arr));
                }
            }
        }
    }

    private function sendToAdmin($ws,$message){
        //admin 当前有账号在线
        $this->sendToUid($ws,1,$message);
    }
}